Templates:

 

All the preceding remarks apply to the macro version of pseudoPODs.  The template version is less efficient and requires more typing, so should be used only by those that really, really hate macros. 

Each pseudoPOD requires 1 pointer in the macro version, versus 3 pointers for the template version, so the memory consumption is higher.  Arrays made from templates are a little worse, requiring 3 pointers plus 1 integer per array element, versus 1 pointer per array element for arrays made from macros.

As for coding labor, the macro approach requires 1 additional line per pseudoPOD, while the template approach requires 4 for an individual pseudoPOD, and 8 for an array.  Macros could reduce the typing required, but that would violate the assumption that the template approach will only be used by those that dislike macros.

Finally, the data within the pseudoPOD's code, including the pointers, is not private - the class has to initialize it, but C++ no longer permits befriending a class through a template argument, so I had to make the data within the pseudoPOD code public, exposing it to accidental corruption by code outside the class.

 

Integer pseudoPODs Using Templates:

ppodt_i <fred_c, int> name; // create

                             // the pseudoPOD

private: int name_value; public: 

 

// place in constructor() of class fred_c

name.ep=this;

name.ep_get = &fred_c::get_name;

name.ep_set = &fred_c::set_name;

 

// the get_name() & set_name(int in) functions

     // are identical to those used

     // for pseudoPODs made by macros.

 

Other Non-Pointer Non-Array Types of pseudoPODs Using Templates:

same as for integer, but for "int" substitute one of "long", "unsigned int", "unsigned long", "short", "unsigned short", "char", "unsigned char", "bool", "float", "double" or "long double".

In addition, for "float", "double", & "long double" change the template name from ppodt_i to ppodt_f.

 

Integer Pointer pseudoPODs Using Templates:

ppodt_p <fred_c, int*> name;    // create

                             // the pseudoPOD

private: int *name_value; public:

 

// place in constructor() of class fred_c

name.ep=this;

name.ep_get = &fred_c::get_name;

name.ep_set = &fred_c::set_name;

 

// the *get_name() & *set_name(int *in) functions

// are identical to those used for

// pseudoPODs made by macros.

 

Other Pointer pseudoPODs Using Templates:

same as for integer, but for "int*" substitute one of "unsigned int*", "unsigned long*", "short*", "unsigned short*", "char*", "unsigned char*", "bool*", "float*", "double*" or "long double*".

In addition, for "float", "double", & "long double" change the template name from ppodt_p_i to ppodt_p_f.

 

Arrays of Integer pseudoPODs Using Templates:

const static int name_array_len = 50;  // create

                             // the pseudoPOD

ppodt_array_i <fred_c, int> name[name_array_len];

private: int name_value[name_array_len]; public:

 

// place in constructor() of class fred_c

for (int i=0; i<name_array_len; ++i) {

     name[i].ep = this;

     name[i].ep_get = &fred_c::get_name;

     name[i].ep_set = &fred_c::set_name;

     name[i].index_value = i;

}

 

// the get_name(int index) &

// set_name(int index, int in) functions

// are identical to those used for

// pseudoPODs made by macros.

 

Arrays of Other Non-Pointer pseudoPODs Using Templates:

same as for integer, but for "int" substitute one of "unsigned int", "unsigned long", "short", "unsigned short", "char", "unsigned char", "bool", "float", "double" or "long double".

In addition, for "float", "double", & "long double" change the template name from ppodt_array_i to ppodt_array_f.

 

Arrays of Integer Pointer pseudoPODs Using Templates:

const static int name_array_len = 39; // create

                             // the pseudoPOD

ppodt_array_p <fred_c, int*> name[name_array_len];

private: int *name_value[name_array_len]; public:

 

// place in constructor() of enclosing class

for (int i=0; i<name_array_len; ++i) {

     name[i].ep = this;

     name[i].ep_get = &fred_c::get_name;

     name[i].ep_set = &fred_c::set_name;

     name[i].index_value = i;

}

 

// the *get_name(int index) &

// *set_name(int index, int *in)

// functions are identical to

// those used for pseudoPODs made by macros.

 

Arrays of Other Pointer pseudoPODs Using Templates:

same as for integer, but for "int*" or "int *" substitute one of "unsigned int*", "unsigned long*", "short*", "unsigned short*", "char*", "unsigned char*", "bool*", "float*", "double*" or "long double*".

 

Read Only or Write Only pseudoPODs Using Templates:

same as before, but add "_ro" or "_wo" to the ppodt_i() call, so that:

ppodt_i()

becomes

ppodt_i_ro() or ppodt_i_wo(),

ppodt_p()

becomes

ppodt_p_ro() or ppodt_p_wo(),

ppodt_array()

becomes

ppodt_array_ro() or ppodt_array_wo(), and

ppodt_array_p()

becomes

ppodt_array_p_ro() or ppodt_array_p_wo()